#coding=utf-8
'''
Created on 2015年5月28日
'''

from functools import wraps
from util_base.exception import UFOException, DBException
from setting_base import setting
from processor_base.meta import ProcessorMeta
import errno
import os
import signal

    
def processor(cmdid, internal_only=False, internal_access=False, web_access=False):
    '''
    装饰器, 用于装饰processor中的主类
            作用是建立协议号和主类的映射
    internal_only: 是否仅支持内部调用
    web_access: 是否支持web调用
    internal_access: 是否支持内部调用
    
    meta: 直接传入一个ProcessorMeta的实例, 此时将无视其他可选参数
    '''
    def _module_dec(cls):
        
        if hasattr(setting, 'processor_mapping'):
            processor_mapping = getattr(setting, 'processor_mapping')
        else:
            processor_mapping = {}
            setattr(setting, 'processor_mapping', processor_mapping)
        
 
        if isinstance(cmdid, tuple):      
            _cmdid = cmdid[0]
        else:
            _cmdid = cmdid
            
        if _cmdid not in processor_mapping:
            processor_mapping[_cmdid] = ProcessorMeta(cls)
        meta = processor_mapping[_cmdid]
        
        meta.internal_only = internal_only
        meta.web_access = web_access
        meta.internal_access = internal_access
        meta.cls = cls
        
        return cls
    return _module_dec

def deprecated_func(func):
    '''
    '''
    
    return func


def db_operator(func):
    '''
    用于修饰数据库操作类(如BaseDB)中的方法, 将异常转化为DBException
    '''
    
    @wraps(func)
    def _dec(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            # 为了保留原异常栈信息, 需要同时raise traceback对象
            raise DBException(e)
                
    return _dec


def exception_transfer(exception_cls):
    '''
    异常转化
    '''
    
    def _dec(func):
        
        @wraps(func)
        def __dec(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except UFOException:
                raise 
            except Exception as e:
                # 为了保留原异常栈信息, 需要同时raise traceback对象
                raise exception_cls(e)
        return __dec
                
    return _dec


    
class TimeoutError(Exception):
    pass

def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
    def decorator(func):
        def _handle_timeout(signum, frame):
            raise TimeoutError(error_message)

        def wrapper(*args, **kwargs):
            signal.signal(signal.SIGALRM, _handle_timeout)
            signal.alarm(seconds)
            try:
                result = func(*args, **kwargs)
            finally:
                signal.alarm(0)
            return result

        return wraps(func)(wrapper)

    return decorator
